<!-- 进度圈组件 -->
<template>
	<view class="cmd-circle">
		<canvas :canvas-id="cid" :style="calCircleStyle" ></canvas>
	</view>
</template>

<script>
	/**
	 * 进度圈组件  
	 * @description 用圈显示一个操作完成的百分比时，为用户显示该操作的当前进度和状态。  
	 * @tutorial https://ext.dcloud.net.cn/plugin?id=259  
	 * @property {String} cid 画布编号 - 默认defaultCanvas  
	 * @property {String} type 进度圈类型 - 圆圈形：circle、仪表盘：dashboard，默认圆圈形：circle  
	 * @property {Number} percent 进度圈百分比值 - 显示范围0-100 ，可能数比较大就需要自己转成百分比的值  
	 * @property {Boolean} show-info 进度圈进度状态信息 - 显示进度数值或状态图标，默认true  
	 * @property {String} font-color 进度圈文字信息颜色  
	 * @property {String} font-size 进度圈文字信息大小 - 默认：14  
	 * @property {String} status 进度圈状态 - 正常：normal、完成：success、失败：exception，默认正常：normal  
	 * @property {Number} stroke-width 进度圈线条宽度 - 建议在条线的宽度范围：1-50，与进度条显示宽度有关，默认：6  
	 * @property {String} stroke-color 进度圈的颜色 - 设置后status状态无效  
	 * @property {String} stroke-background 进度圈的底圈颜色 - 默认：#eeeeee  
	 * @property {String} stroke-shape 进度圈两端的形状 - 圆：round、方直角：square，默认圆：round  
	 * @property {Number} width 进度圈布宽度 - 默认80  
	 * @property {String} gap-degree 进度圈形缺口角度 - 可取值 0 ~ 360，仅支持类型：circle  
	 * @property {String} gap-position 进度圈形缺口位置 - 可取值'top', 'bottom', 'left', 'right'，仅支持类型：circle  
	 * @example <cmd-circle id="circle1" type="circle" :percent="75"></cmd-circle>  
	 */
	export default {
		name: "cmd-circle",

		props: {
			// 画布编号 默认defaultCanvas
			cid: {
				type: String,
				default: "defaultCanvas"
			},
			// 圈类型默认：circle，可选 circle dashboard
			type: {
				type: String,
				validator: val => {
					return ['circle', 'dashboard'].includes(val);
				},
				default: 'circle'
			},
			// 圈进度百分比值
			percent: {
				type: Number,
				validator: val => {
					return val >= 0 && val <= 100;
				},
				default: 0
			},
			//圈中显示的数字信息
			text:{
				type:Number,
				default:0
			},
			
			// 圈是否显示进度数值或状态图标
			showInfo: {
				type: Boolean,
				default: true
			},
			// 圈文字信息颜色
			fontColor: {
				type: String,
				default: "#595959"
			},
			// 圈文字信息大小 默认14
			fontSize: {
				type: Number,
				default: 14
			},
			// 圈进度状态，可选：normal success exception
			status: {
				type: String,
				validator: val => {
					return ['normal', 'success', 'exception'].includes(val);
				},
				default: 'normal'
			},
			// 圈线条宽度1-50，与width有关
			strokeWidth: {
				type: Number,
				default: 6
			},
			// 圈的颜色，设置后status状态无效
			strokeColor: {
				type: String,
				default: ''
			},
			// 圈的底圈颜色 默认：#eeeeee
			strokeBackground: {
				type: String,
				default: '#eeeeee'
			},
			// 圈两端的形状 可选：'round', 'square'
			strokeShape: {
				type: String,
				validator: val => {
					return ['round', 'square'].includes(val);
				},
				default: 'round'
			},
			// 圈画布宽度
			width: {
				type: Number,
				default: 180
			},
			// 圈缺口角度，可取值 0 ~ 360，仅支持类型：circle  
			gapDegree: {
				type: Number,
				validator: val => {
					return val >= 0 && val <= 360;
				},
				default: 360
			},
			// 圈缺口开始位置,可取值'top', 'bottom', 'left', 'right'，仅支持类型：circle  
			gapPosition: {
				type: String,
				validator: val => {
					return ['top', 'bottom', 'left', 'right'].includes(val);
				},
				default: 'top'
			}
		},

		data() {
			return {
				// 画布实例
				ctx: {},
				// 圈半径
				width2px: ""
			}
		},

		computed: {
			// 计算设置圈样式
			calCircleStyle() {
				return `width: ${this.width}px;
				height: ${this.width}px;`
			},
			// 计算圈状态
			calStatus() {
				let status = {}
				switch (this.status) {
					case 'normal':
						status = {
							color: "#1890ff",
							value: 1
						};
						break;
					case 'success':
						status = {
							color: "#52c41a",
							value: 2
						};
						break;
					case 'exception':
						status = {
							color: "#f5222d",
							value: 3
						};
						break;
				}
				return status
			},
			// 计算圈缺口角度
			calGapDegree() {
				return this.gapDegree <= 0 ? 360 : this.gapDegree
			},
			// 计算圈缺口位置
			calGapPosition() {
				let gapPosition = 0
				switch (this.gapPosition) {
					case 'bottom':
						gapPosition = 90;
						break;
					case 'left':
						gapPosition = 180;
						break;
					case 'top':
						gapPosition = 270;
						break;
					case 'right':
						gapPosition = 360;
						break;
				}
				return gapPosition
			},
		},

		watch: {
			// 监听百分比值改变
			percent(val) {
				this.drawStroke(val);
			}
		},

		mounted() {
			// 创建画布实例
			this.ctx = uni.createCanvasContext(this.cid, this)
			// upx转px 圈半径大小
			this.width2px = uni.upx2px(this.width)
			// 绘制初始 
			this.$nextTick(() => {
				this.drawStroke(this.percent)
			})
		},

		methods: {
			// 绘制圈
			drawStroke(percent) {
				percent = percent >= 100 ? 100 : percent < 0 ? 0 : percent
				// 圈条进度色
				let color = this.strokeColor || this.calStatus.color
				// 设置字体
				this.drawText(this.text)
				// // 是否圈中心显示信息
				// if (this.showInfo) {
				// 	switch (this.calStatus.value) {
				// 		case 1:
				// 			if (percent >= 100) {
				// 				// 设置打勾
				// 				this.drawSuccess()
				// 				percent = 100
				// 				color = "#52c41a"
				// 			} else {
				// 				// 设置字体
				// 				this.drawText(percent)
				// 			}
				// 			break;
				// 		case 2:
				// 			// 设置打勾
				// 			this.drawSuccess()
				// 			percent = 100
				// 			color = "#52c41a"
				// 			break;
				// 		case 3:
				// 			// 设置打叉
				// 			this.drawException()
				// 			percent = 0
				// 			color = "#f5222d"
				// 			break;
				// 		default:
				// 			break;
				// 	}
				// }
				// 缺口
				let gapPosition = this.calGapPosition
				let gapDegree = this.calGapDegree
				// 仪表固定
				if (this.type === "dashboard") {
					gapPosition = 135
					gapDegree = 270
				}
				// 圈型条宽
				this.ctx.setLineCap(this.strokeShape)
				this.ctx.setLineWidth(this.strokeWidth)
				// 位置原点
				this.ctx.translate(this.width2px, this.width2px)
				// 缺口方向 
				this.ctx.rotate(gapPosition * Math.PI / 180)
				// 圈底 
				this.ctx.beginPath()
				this.ctx.arc(0, 0, this.width2px - this.strokeWidth, 0, gapDegree * Math.PI / 180)
				this.ctx.setStrokeStyle(this.strokeBackground)
				this.ctx.stroke()
				// 圈进度 
				this.ctx.beginPath()
				this.ctx.arc(0, 0, this.width2px - this.strokeWidth, 0, percent * gapDegree * Math.PI / 18000)
				this.ctx.setStrokeStyle(color)
				this.ctx.stroke()
			
				//绘制文字底图背景圆形
				this.drawCicle()
				
				// 绘制
				this.ctx.draw()
			},
			// 绘制文字格式
			drawText(text) {
				this.ctx.beginPath()
				this.ctx.setFontSize(this.fontSize)
				this.ctx.setFillStyle(this.fontColor)
				this.ctx.setTextAlign('center')
				//文字加粗 将文字绘制两遍
				this.ctx.fillText(`${text}`, this.width2px, this.width2px-0.5 )
				this.ctx.fillText(`${text}`, this.width2px-0.5, this.width2px )
				this.ctx.setFontSize(16)
				
				this.ctx.setFillStyle(this.fontColor)
				this.ctx.setTextAlign('center')
				this.ctx.fillText(`分`, this.width2px, this.width2px + this.fontSize)
				
				this.ctx.stroke()
			},
			//绘制文字底图圆形
			drawCicle() {
				this.ctx.beginPath()
				this.ctx.arc(0, 0, this.width2px-20, 0, 2 * Math.PI)
				this.ctx.setFillStyle('rgba(199, 226, 255, 0.1)')
				this.ctx.fill()
			},
			// 绘制成功打勾
			drawSuccess() {
				let x = this.width2px - this.fontSize / 2
				let y = this.width2px + this.fontSize / 2
				this.ctx.beginPath()
				this.ctx.setLineCap('round')
				this.ctx.setLineWidth(this.fontSize / 4)
				this.ctx.moveTo(this.width2px, y)
				this.ctx.lineTo(y, x)
				this.ctx.moveTo(this.width2px, y)
				this.ctx.lineTo(x, this.width2px)
				this.ctx.setStrokeStyle("#52c41a")
				this.ctx.stroke()
			},
			// 绘制异常打叉
			drawException() {
				let x = this.width2px - this.fontSize / 2
				let y = this.width2px + this.fontSize / 2
				this.ctx.beginPath()
				this.ctx.setLineCap('round')
				this.ctx.setLineWidth(this.fontSize / 4)
				this.ctx.moveTo(x, x)
				this.ctx.lineTo(y, y)
				this.ctx.moveTo(y, x)
				this.ctx.lineTo(x, y)
				this.ctx.setStrokeStyle("#f5222d")
				this.ctx.stroke()
			}
		}
	};
</script>

<style>
	.cmd-circle {
		display: inline-block;
		box-sizing: border-box;
		list-style: none;
		margin: 0;
		padding: 0;
	}
</style>
